package nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * 零拷贝
 * 关键代码 ByteBuffer.allocateDirect(10);
 * 和前面allocate的区别在于，它是通过字节数组来创建的。也就是说你现在可以直接修改底层字节数组来改变值
 * 直接缓存和间接缓存一个区别就是，直接缓存调用的native方法来实现的。
 * 向之前的heapbuffer都是使用的java的对象来实现缓存中，还有那个wrap实现使用的是字节数组。
 */
public class NioTestStart {
    public static void main(String[] args) throws IOException {

        int[] prots = new int[5];
        prots[0] = 5000;
        prots[1] = 5001;
        prots[2] = 5002;
        prots[3] = 5003;
        prots[4] = 5004;
        Selector selector = Selector.open();
        for (int i = 0; i < prots.length; i++) {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

            serverSocketChannel.configureBlocking(false);

            serverSocketChannel.bind(new InetSocketAddress(prots[i]));

            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("监听端口： "+prots[i]);
        }
        while (true) {
            int numbers = selector.select();
            System.out.println("numbers： " + numbers);

            Set<SelectionKey> selectionKeys = selector.selectedKeys();

            System.out.println("selectionKeys " + selectionKeys);

            Iterator<SelectionKey> selectionKeyIterator = selectionKeys.iterator();
            while (selectionKeyIterator.hasNext()) {
                SelectionKey selectionKey = selectionKeyIterator.next();

                if (selectionKey.isAcceptable()) {
                    ServerSocketChannel serverSocketChannel = (ServerSocketChannel)selectionKey.channel();
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    // 相当于CallBack回去然后再进来一次循环进行下一次操作 多路复用
                    socketChannel.register(selector, SelectionKey.OP_READ);
                    selectionKeyIterator.remove();
                }else if (selectionKey.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel)selectionKey.channel();

                    int byteReadIndex = 0 ;
                    ByteBuffer byteBuffer = ByteBuffer.allocate(2);
                    while (true) {
                        byteBuffer.clear();
                        int read = socketChannel.read(byteBuffer);
                        if (read <= 0 ){
                            break;
                        }
                        byteBuffer.flip();
                        socketChannel.write(byteBuffer);
                        byteReadIndex += read;

                    }
                    System.out.println("读取长度为: "+ byteReadIndex);
                    selectionKeyIterator.remove();
                }
            }
        }
    }
}
